Number of Running and Waiting threads over time

The spikes happened when I was messing around with Jenkins, installing few plugins and running some dummy tasks. you can zoom and move around the plot

plot = function(data) {
  g <- data %>% ggplot(aes(Date, freq)) + 
    geom_line(aes(color=NewState)) +
    labs(colour="State") +
    theme_bw() +
    ylab("No. Of Threads") +
    xlab("Date/Time") +
    ggtitle("Frequency of Running vs. Waiting Threads Over Time")
  ggplotly(g, tooltip = "all")
}
threashold = as.POSIXct("2018-01-18 1900", format="%Y-%m-%d %H%M", tz = Sys.getenv('TZ'))
freq_data = count(data, vars=c("NewState", "Time"))
freq_data$Date = as.POSIXct(freq_data$Time, origin="1970-01-01")
# freq_data = freq_data[freq_data$Date > threashold, ]
plot(freq_data)

A specific thread change of states over time:

The thread went into running state when I was executing a build, then went to waiting again after finishing

my_data = data[data$ID == '139939698210816',]
my_data$NewState = as.factor(my_data$NewState)
my_data$group = 1
my_data$Time = as.POSIXct(my_data$Time, origin="1970-01-01")
my_data %>% ggplot(aes(Time, NewState, group = group)) + 
  geom_point(aes(color=my_data$Name)) + 
  scale_y_discrete(limits = rev(levels(my_data$NewState))) +
  labs(colour="Thread Name") +
  theme_bw() +
  theme(legend.position = "top", plot.title = element_text(size=9, face="bold", hjust = 0.5)) +
  ylab("State") +
  xlab("Time") +
  ggtitle(paste("Thread ID ", my_data$ID)) +
  guides(colour = guide_legend(nrow = 2,
                               label.theme = element_text(angle=0,size=7),
                               title.position = "top", 
                               title.theme = element_text(angle=0,face="bold", size=7)))

NA
NA

In the following two, the same thread with the same ID has a different name every time it goes into the Running state. The reason is that in the Jenkins implementation, it looks that they change the thread name each time the thread is handling an HTTP request

my_data = data[data$ID == '139938960125952',]
my_data$NewState = as.factor(my_data$NewState)
my_data$group = 1
my_data %>% ggplot(aes(Time, NewState, group = group)) + 
  geom_line(aes(color=my_data$Name)) + 
  scale_y_discrete(limits = rev(levels(my_data$NewState))) +
  labs(colour="Thread Name") +
  theme_bw() +
  theme(legend.position = "top") +
  ylab("State") +
  xlab("Time") +
  ggtitle(paste("Thread ID ", my_data$ID)) +
  guides(colour = guide_legend(nrow = 1,
                               label.theme = element_text(angle=0,size=7),
                               title.position = "top", 
                               title.theme = element_text(angle=0,face="bold", size=7)))

g <- my_data %>% ggplot(aes(Time, NewState, group = group)) + 
  geom_point(aes(color=my_data$Name)) + 
  scale_y_discrete(limits = rev(levels(my_data$NewState))) +
  labs(colour="Thread Name") +
  theme_bw() +
  theme(legend.position = "top") +
  ylab("State") +
  xlab("Time") +
  ggtitle(paste("Thread ID ", my_data$ID)) +
  guides(colour = guide_legend(nrow = 1,
                               label.theme = element_text(angle=0,size=7),
                               title.position = "top", 
                               title.theme = element_text(angle=0,face="bold", size=7)))
g

The threads go into the running state for a very brief time periods then back into waiting, because the requests are not time consuming (no heavy logic or database queries involved), even the second plot that was plotting the thread executing a Jenkins build job was very short, because the task I ran was a dummy one executing very fast.

So, I tried running another task that would just sleep form some time and sampled a thread dump every 1 second so the thread would stay in the running state for some time. However, what happened is I got missing values for some of the time points e.g. (31:37) it means that the thread dump at that second didn’t contain the thread with the ID “139939027800064”. I don’t know why would that happend (needs more investigation)

data = load_data("thread_data_day2.csv")
my_data = data[data$ID == "139939027800064",]
my_data$NewState = as.factor(my_data$NewState)
my_data$group = 1
my_data$Time = as.POSIXct(my_data$Time, origin="1970-01-01")
my_data %>% ggplot(aes(Time, NewState, group = group)) + 
  geom_point(aes(color=my_data$Name,), alpha=0.6) + 
  scale_y_discrete(limits = rev(levels(my_data$NewState))) +
  labs(colour="Thread Name") +
  theme_bw() +
  theme(legend.position = "top", plot.title = element_text(size=9, face="bold", hjust = 0.5)) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  ylab("State") +
  xlab("Time") +
  ggtitle(paste("Thread ID ", my_data$ID)) +
  scale_x_datetime(labels = date_format("%M:%S"), date_breaks = "2 sec") +
  guides(colour = guide_legend(nrow = 2,
                               label.theme = element_text(angle=0,size=7),
                               title.position = "top", 
                               title.theme = element_text(angle=0,face="bold", size=7)))

NA
NA
ids = data$ID %>% unique
for(id in ids) {
  len = data[data$ID == id,]$NewState %>% unique %>% length
  if(len > 1) {
    print(id)
    (data[data$ID == id,]$NewState == "Running") %>% sum %>% print
    # print(data[data$ID == id,]$Name %>% unique)
  }
}
[1] "139939769366528"
[1] 1
[1] "139939027800064"
[1] 2
[1] "94248643735552"
[1] 2
[1] "139939295555584"
[1] 1
[1] "139940246913024"
[1] 1
[1] "139940246902784"
[1] 1
# 
# list_ids = sapply(data$ID, function(x) {
#   len = data[data$ID == x,]$NewState %>% unique %>% length
#   if(len > 1) id else NA
# }, simplify = TRUE)

Frequency of different thread priorities over time

This shows the frequency of different thread priorites. Ofcourse they have the same spikes like the above graphs and the most frequent priority is 5 since it’s the default priority the JVM uses for new threads

freq_data = count(data, vars=c("Prio", "Time"))
freq_data$Date = as.POSIXct(freq_data$Time, origin="1970-01-01")
freq_data$Prio = freq_data$Prio %>% sapply(function(x){if(x == -1){"Missing"}else{x}})
freq_data$Prio = as.factor(freq_data$Prio)
g <- freq_data %>% ggplot(aes(Date, freq)) + 
    geom_line(aes(color=Prio)) +
    labs(colour="Priority") +
    ylab("No. Of Threads") +
    xlab("Date/Time") +
    ggtitle("Frequency of Threads With Diff. Priorities Over Time") 
ggplotly(g, tooltip = "all")
LS0tCnRpdGxlOiAiU29tZSBQbG90cyBFeHBsb3JpbmcgQSBKZW5raW5zIFRocmVhZCBEdW1wIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIHRoZW1lOiB1bml0ZQotLS0KCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+Cgpib2R5ewogICAgICBmb250LXNpemU6IDE4cHg7Cn0KPC9zdHlsZT4KCmBgYHtyIHJlc3VsdHM9J2hpZGUnLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoY2FjaGUgPSBUUlVFKQojIGtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcud2lkdGg9MTApIApsaWJyYXJ5KHBseXIsIHdhcm4uY29uZmxpY3RzID0gRkFMU0UpCmxpYnJhcnkoZ2dwbG90Miwgd2Fybi5jb25mbGljdHMgPSBGQUxTRSkKbGlicmFyeShzdHJpbmdyLCB3YXJuLmNvbmZsaWN0cyA9IEZBTFNFKQpsaWJyYXJ5KHBsb3RseSwgd2Fybi5jb25mbGljdHMgPSBGQUxTRSkKbGlicmFyeShzY2FsZXMpClN5cy5zZXRlbnYoVFo9IkV1cm9wZS9WaWVubmEiKQpzZXR3ZCgifi93b3Jrc3BhY2UvcmVwb3MvdGhyZWFkLWxvY2stYW5hbHlzaXMvUiBPdmVydmlldy8iKQpgYGAKCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBjYWNoZT1UUlVFLCBpbmNsdWRlPUZBTFNFfQpsb2FkX2RhdGEgPSBmdW5jdGlvbihmaWxlbmFtZSkgewogIGRhdGEgPSByZWFkLmNzdihoZWFkZXIgPSBGQUxTRSwgZmlsZW5hbWUsIGNvbC5uYW1lcyA9IGMoIklEIiwgIk5hbWUiLCAiUHJpbyIsICJTdGF0ZSIsICJUaW1lIikpCiAgZGF0YSROZXdTdGF0ZSA9IHNhcHBseShkYXRhJFN0YXRlLCBmdW5jdGlvbih4KSB7CiAgICBpZihzdHJfY291bnQoeCwgIndhaXQiKSA+IDApIHsKICAgICAgIldhaXRpbmciCiAgICB9ZWxzZSAiUnVubmluZyIKICB9KQogIGRhdGEkSUQgPSBhcy5jaGFyYWN0ZXIoZGF0YSRJRCkKICBkYXRhJE5hbWUgPSBzYXBwbHkoZGF0YSROYW1lLCBmdW5jdGlvbih4KSB7CiAgICBzdHJfc3BsaXQoeCwgIiBmcm9tIiwgc2ltcGxpZnkgPSBUUlVFKVsxXQogIH0pCiAgZGF0YQp9CmRhdGEgPSBsb2FkX2RhdGEoInRocmVhZF9kYXRhLmNzdiIpCmBgYAoKCgojIyBOdW1iZXIgb2YgUnVubmluZyBhbmQgV2FpdGluZyB0aHJlYWRzIG92ZXIgdGltZQoKVGhlIHNwaWtlcyBoYXBwZW5lZCB3aGVuIEkgd2FzIG1lc3NpbmcgYXJvdW5kIHdpdGggSmVua2lucywgaW5zdGFsbGluZyBmZXcgcGx1Z2lucyBhbmQgcnVubmluZyBzb21lIGR1bW15IHRhc2tzLiB5b3UgY2FuIHpvb20gYW5kIG1vdmUgYXJvdW5kIHRoZSBwbG90CmBgYHtyIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPVRSVUUsIGRwaT0xMjAsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTV9CnBsb3QgPSBmdW5jdGlvbihkYXRhKSB7CiAgZyA8LSBkYXRhICU+JSBnZ3Bsb3QoYWVzKERhdGUsIGZyZXEpKSArIAogICAgZ2VvbV9saW5lKGFlcyhjb2xvcj1OZXdTdGF0ZSkpICsKICAgIGxhYnMoY29sb3VyPSJTdGF0ZSIpICsKICAgIHRoZW1lX2J3KCkgKwogICAgeWxhYigiTm8uIE9mIFRocmVhZHMiKSArCiAgICB4bGFiKCJEYXRlL1RpbWUiKSArCiAgICBnZ3RpdGxlKCJGcmVxdWVuY3kgb2YgUnVubmluZyB2cy4gV2FpdGluZyBUaHJlYWRzIE92ZXIgVGltZSIpCiAgZ2dwbG90bHkoZywgdG9vbHRpcCA9ICJhbGwiKQp9CnRocmVhc2hvbGQgPSBhcy5QT1NJWGN0KCIyMDE4LTAxLTE4IDE5MDAiLCBmb3JtYXQ9IiVZLSVtLSVkICVIJU0iLCB0eiA9IFN5cy5nZXRlbnYoJ1RaJykpCmZyZXFfZGF0YSA9IGNvdW50KGRhdGEsIHZhcnM9YygiTmV3U3RhdGUiLCAiVGltZSIpKQpmcmVxX2RhdGEkRGF0ZSA9IGFzLlBPU0lYY3QoZnJlcV9kYXRhJFRpbWUsIG9yaWdpbj0iMTk3MC0wMS0wMSIpCiMgZnJlcV9kYXRhID0gZnJlcV9kYXRhW2ZyZXFfZGF0YSREYXRlID4gdGhyZWFzaG9sZCwgXQpwbG90KGZyZXFfZGF0YSkKYGBgCgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgY2FjaGU9VFJVRSwgZWNobz1GQUxTRX0KIyBpZHMgPSBkYXRhJElEICU+JSB1bmlxdWUKIyBmb3IoaWQgaW4gaWRzKSB7CiMgICBsZW4gPSBkYXRhW2RhdGEkSUQgPT0gaWQsXSROZXdTdGF0ZSAlPiUgdW5pcXVlICU+JSBsZW5ndGgKIyAgIGlmKGxlbiA+IDEpIHByaW50KGlkKQojIH0KYGBgCgojIyBBIHNwZWNpZmljIHRocmVhZCBjaGFuZ2Ugb2Ygc3RhdGVzIG92ZXIgdGltZToKCgpUaGUgdGhyZWFkIHdlbnQgaW50byBydW5uaW5nIHN0YXRlIHdoZW4gSSB3YXMgZXhlY3V0aW5nIGEgYnVpbGQsIHRoZW4gd2VudCB0byB3YWl0aW5nIGFnYWluIGFmdGVyIGZpbmlzaGluZwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBkcGk9MTIwfQpteV9kYXRhID0gZGF0YVtkYXRhJElEID09ICcxMzk5Mzk2OTgyMTA4MTYnLF0KbXlfZGF0YSROZXdTdGF0ZSA9IGFzLmZhY3RvcihteV9kYXRhJE5ld1N0YXRlKQpteV9kYXRhJGdyb3VwID0gMQoKbXlfZGF0YSRUaW1lID0gYXMuUE9TSVhjdChteV9kYXRhJFRpbWUsIG9yaWdpbj0iMTk3MC0wMS0wMSIpCm15X2RhdGEgJT4lIGdncGxvdChhZXMoVGltZSwgTmV3U3RhdGUsIGdyb3VwID0gZ3JvdXApKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG9yPW15X2RhdGEkTmFtZSkpICsgCiAgc2NhbGVfeV9kaXNjcmV0ZShsaW1pdHMgPSByZXYobGV2ZWxzKG15X2RhdGEkTmV3U3RhdGUpKSkgKwogIGxhYnMoY29sb3VyPSJUaHJlYWQgTmFtZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTksIGZhY2U9ImJvbGQiLCBoanVzdCA9IDAuNSkpICsKICB5bGFiKCJTdGF0ZSIpICsKICB4bGFiKCJUaW1lIikgKwogIGdndGl0bGUocGFzdGUoIlRocmVhZCBJRCAiLCBteV9kYXRhJElEKSkgKwogIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQobnJvdyA9IDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbC50aGVtZSA9IGVsZW1lbnRfdGV4dChhbmdsZT0wLHNpemU9NyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZS5wb3NpdGlvbiA9ICJ0b3AiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlLnRoZW1lID0gZWxlbWVudF90ZXh0KGFuZ2xlPTAsZmFjZT0iYm9sZCIsIHNpemU9NykpKQogIAogIApgYGAKCgoKSW4gdGhlIGZvbGxvd2luZyB0d28sIHRoZSBzYW1lIHRocmVhZCB3aXRoIHRoZSBzYW1lIElEIGhhcyBhIGRpZmZlcmVudCBuYW1lIGV2ZXJ5IHRpbWUgaXQgZ29lcyBpbnRvIHRoZSBSdW5uaW5nIHN0YXRlLiBUaGUgcmVhc29uIGlzIHRoYXQgaW4gdGhlIEplbmtpbnMgaW1wbGVtZW50YXRpb24sIGl0IGxvb2tzIHRoYXQgdGhleSBjaGFuZ2UgdGhlIHRocmVhZCBuYW1lIGVhY2ggdGltZSB0aGUgdGhyZWFkIGlzIGhhbmRsaW5nIGFuIEhUVFAgcmVxdWVzdCAKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZHBpPTEyMH0KbXlfZGF0YSA9IGRhdGFbZGF0YSRJRCA9PSAnMTM5OTM4OTYwMTI1OTUyJyxdCm15X2RhdGEkTmV3U3RhdGUgPSBhcy5mYWN0b3IobXlfZGF0YSROZXdTdGF0ZSkKbXlfZGF0YSRncm91cCA9IDEKCm15X2RhdGEgJT4lIGdncGxvdChhZXMoVGltZSwgTmV3U3RhdGUsIGdyb3VwID0gZ3JvdXApKSArIAogIGdlb21fbGluZShhZXMoY29sb3I9bXlfZGF0YSROYW1lKSkgKyAKICBzY2FsZV95X2Rpc2NyZXRlKGxpbWl0cyA9IHJldihsZXZlbHMobXlfZGF0YSROZXdTdGF0ZSkpKSArCiAgbGFicyhjb2xvdXI9IlRocmVhZCBOYW1lIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLCBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9OSwgZmFjZT0iYm9sZCIsIGhqdXN0ID0gMC41KSkgKwogIHlsYWIoIlN0YXRlIikgKwogIHhsYWIoIlRpbWUiKSArCiAgZ2d0aXRsZShwYXN0ZSgiVGhyZWFkIElEICIsIG15X2RhdGEkSUQpKSArCiAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChucm93ID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsLnRoZW1lID0gZWxlbWVudF90ZXh0KGFuZ2xlPTAsc2l6ZT03KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlLnBvc2l0aW9uID0gInRvcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUudGhlbWUgPSBlbGVtZW50X3RleHQoYW5nbGU9MCxmYWNlPSJib2xkIiwgc2l6ZT03KSkpCmBgYAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZHBpPTEyMH0KZyA8LSBteV9kYXRhICU+JSBnZ3Bsb3QoYWVzKFRpbWUsIE5ld1N0YXRlLCBncm91cCA9IGdyb3VwKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1teV9kYXRhJE5hbWUpKSArIAogIHNjYWxlX3lfZGlzY3JldGUobGltaXRzID0gcmV2KGxldmVscyhteV9kYXRhJE5ld1N0YXRlKSkpICsKICBsYWJzKGNvbG91cj0iVGhyZWFkIE5hbWUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIsIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT05LCBmYWNlPSJib2xkIiwgaGp1c3QgPSAwLjUpKSArCiAgeWxhYigiU3RhdGUiKSArCiAgeGxhYigiVGltZSIpICsKICBnZ3RpdGxlKHBhc3RlKCJUaHJlYWQgSUQgIiwgbXlfZGF0YSRJRCkpICsKICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG5yb3cgPSAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwudGhlbWUgPSBlbGVtZW50X3RleHQoYW5nbGU9MCxzaXplPTcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUucG9zaXRpb24gPSAidG9wIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZS50aGVtZSA9IGVsZW1lbnRfdGV4dChhbmdsZT0wLGZhY2U9ImJvbGQiLCBzaXplPTcpKSkKZwpgYGAKClRoZSB0aHJlYWRzIGdvIGludG8gdGhlIHJ1bm5pbmcgc3RhdGUgZm9yIGEgdmVyeSBicmllZiB0aW1lIHBlcmlvZHMgdGhlbiBiYWNrIGludG8gd2FpdGluZywgYmVjYXVzZSB0aGUgcmVxdWVzdHMgYXJlIG5vdCB0aW1lIGNvbnN1bWluZyAobm8gaGVhdnkgbG9naWMgb3IgZGF0YWJhc2UgcXVlcmllcyBpbnZvbHZlZCksIGV2ZW4gdGhlIHNlY29uZCBwbG90IHRoYXQgd2FzIHBsb3R0aW5nIHRoZSB0aHJlYWQgZXhlY3V0aW5nIGEgSmVua2lucyBidWlsZCBqb2Igd2FzIHZlcnkgc2hvcnQsIGJlY2F1c2UgdGhlIHRhc2sgSSByYW4gd2FzIGEgZHVtbXkgb25lIGV4ZWN1dGluZyB2ZXJ5IGZhc3QuIAoKU28sIEkgdHJpZWQgcnVubmluZyBhbm90aGVyIHRhc2sgdGhhdCB3b3VsZCBqdXN0IHNsZWVwIGZvcm0gc29tZSB0aW1lIGFuZCBzYW1wbGVkIGEgdGhyZWFkIGR1bXAgZXZlcnkgMSBzZWNvbmQgc28gdGhlIHRocmVhZCB3b3VsZCBzdGF5IGluIHRoZSBydW5uaW5nIHN0YXRlIGZvciBzb21lIHRpbWUuIEhvd2V2ZXIsIHdoYXQgaGFwcGVuZWQgaXMgSSBnb3QgbWlzc2luZyB2YWx1ZXMgZm9yIHNvbWUgb2YgdGhlIHRpbWUgcG9pbnRzIGUuZy4gKDMxOjM3KSBpdCBtZWFucyB0aGF0IHRoZSB0aHJlYWQgZHVtcCBhdCB0aGF0IHNlY29uZCBkaWRuJ3QgY29udGFpbiB0aGUgdGhyZWFkIHdpdGggdGhlIElEICIxMzk5MzkwMjc4MDAwNjQiLiBJIGRvbid0IGtub3cgd2h5IHdvdWxkIHRoYXQgaGFwcGVuZCAobmVlZHMgbW9yZSBpbnZlc3RpZ2F0aW9uKQpgYGB7ciwgZHBpPTEyMH0KZGF0YSA9IGxvYWRfZGF0YSgidGhyZWFkX2RhdGFfZGF5Mi5jc3YiKQpteV9kYXRhID0gZGF0YVtkYXRhJElEID09ICIxMzk5MzkwMjc4MDAwNjQiLF0KbXlfZGF0YSROZXdTdGF0ZSA9IGFzLmZhY3RvcihteV9kYXRhJE5ld1N0YXRlKQpteV9kYXRhJGdyb3VwID0gMQoKbXlfZGF0YSRUaW1lID0gYXMuUE9TSVhjdChteV9kYXRhJFRpbWUsIG9yaWdpbj0iMTk3MC0wMS0wMSIpCm15X2RhdGEgJT4lIGdncGxvdChhZXMoVGltZSwgTmV3U3RhdGUsIGdyb3VwID0gZ3JvdXApKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG9yPW15X2RhdGEkTmFtZSwpLCBhbHBoYT0wLjYpICsgCiAgc2NhbGVfeV9kaXNjcmV0ZShsaW1pdHMgPSByZXYobGV2ZWxzKG15X2RhdGEkTmV3U3RhdGUpKSkgKwogIGxhYnMoY29sb3VyPSJUaHJlYWQgTmFtZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTksIGZhY2U9ImJvbGQiLCBoanVzdCA9IDAuNSkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgeWxhYigiU3RhdGUiKSArCiAgeGxhYigiVGltZSIpICsKICBnZ3RpdGxlKHBhc3RlKCJUaHJlYWQgSUQgIiwgbXlfZGF0YSRJRCkpICsKICBzY2FsZV94X2RhdGV0aW1lKGxhYmVscyA9IGRhdGVfZm9ybWF0KCIlTTolUyIpLCBkYXRlX2JyZWFrcyA9ICIyIHNlYyIpICsKICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG5yb3cgPSAyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwudGhlbWUgPSBlbGVtZW50X3RleHQoYW5nbGU9MCxzaXplPTcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUucG9zaXRpb24gPSAidG9wIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZS50aGVtZSA9IGVsZW1lbnRfdGV4dChhbmdsZT0wLGZhY2U9ImJvbGQiLCBzaXplPTcpKSkKICAKICAKYGBgCgpgYGB7cn0KIyBpZHMgPSBkYXRhJElEICU+JSB1bmlxdWUKIyBmb3IoaWQgaW4gaWRzKSB7CiMgICBsZW4gPSBkYXRhW2RhdGEkSUQgPT0gaWQsXSROZXdTdGF0ZSAlPiUgdW5pcXVlICU+JSBsZW5ndGgKIyAgIGlmKGxlbiA+IDEpIHsKIyAgICAgcHJpbnQoaWQpCiMgICAgIChkYXRhW2RhdGEkSUQgPT0gaWQsXSROZXdTdGF0ZSA9PSAiUnVubmluZyIpICU+JSBzdW0gJT4lIHByaW50CiMgICAgICMgcHJpbnQoZGF0YVtkYXRhJElEID09IGlkLF0kTmFtZSAlPiUgdW5pcXVlKQojICAgfQojIH0KIyAKIyBsaXN0X2lkcyA9IHNhcHBseShkYXRhJElELCBmdW5jdGlvbih4KSB7CiMgICBsZW4gPSBkYXRhW2RhdGEkSUQgPT0geCxdJE5ld1N0YXRlICU+JSB1bmlxdWUgJT4lIGxlbmd0aAojICAgaWYobGVuID4gMSkgaWQgZWxzZSBOQQojIH0sIHNpbXBsaWZ5ID0gVFJVRSkKYGBgCgoKCiMjIEZyZXF1ZW5jeSBvZiBkaWZmZXJlbnQgdGhyZWFkIHByaW9yaXRpZXMgb3ZlciB0aW1lCgoKVGhpcyBzaG93cyB0aGUgZnJlcXVlbmN5IG9mIGRpZmZlcmVudCB0aHJlYWQgcHJpb3JpdGVzLiBPZmNvdXJzZSB0aGV5IGhhdmUgdGhlIHNhbWUgc3Bpa2VzIGxpa2UgdGhlIGFib3ZlIGdyYXBocyBhbmQgdGhlIG1vc3QgZnJlcXVlbnQgcHJpb3JpdHkgaXMgNSBzaW5jZSBpdCdzIHRoZSBkZWZhdWx0IHByaW9yaXR5IHRoZSBKVk0gdXNlcyBmb3IgbmV3IHRocmVhZHMKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZHBpPTEyMCwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NX0KZGF0YSA9IGxvYWRfZGF0YSgidGhyZWFkX2RhdGEuY3N2IikKZnJlcV9kYXRhID0gY291bnQoZGF0YSwgdmFycz1jKCJQcmlvIiwgIlRpbWUiKSkKZnJlcV9kYXRhJERhdGUgPSBhcy5QT1NJWGN0KGZyZXFfZGF0YSRUaW1lLCBvcmlnaW49IjE5NzAtMDEtMDEiKQpmcmVxX2RhdGEkUHJpbyA9IGZyZXFfZGF0YSRQcmlvICU+JSBzYXBwbHkoZnVuY3Rpb24oeCl7aWYoeCA9PSAtMSl7Ik1pc3NpbmcifWVsc2V7eH19KQpmcmVxX2RhdGEkUHJpbyA9IGFzLmZhY3RvcihmcmVxX2RhdGEkUHJpbykKCmcgPC0gZnJlcV9kYXRhICU+JSBnZ3Bsb3QoYWVzKERhdGUsIGZyZXEpKSArIAogICAgZ2VvbV9saW5lKGFlcyhjb2xvcj1QcmlvKSkgKwogICAgbGFicyhjb2xvdXI9IlByaW9yaXR5IikgKwogICAgeWxhYigiTm8uIE9mIFRocmVhZHMiKSArCiAgICB4bGFiKCJEYXRlL1RpbWUiKSArCiAgICBnZ3RpdGxlKCJGcmVxdWVuY3kgb2YgVGhyZWFkcyBXaXRoIERpZmYuIFByaW9yaXRpZXMgT3ZlciBUaW1lIikgCgpnZ3Bsb3RseShnLCB0b29sdGlwID0gImFsbCIpCmBgYAoK